#include "openmove_Prefix.h"
#include "SceneBase.h"
#include "OgreEngine.h"
#include "ExampleFrameListener.h"
#include "SkeletalAnimationFrameListener.h"
#include "OgreExternalTextureSourceManager.h"
#include "OgreExternalTextureSource.h"
#include "SceneInBed.h"
#include "SimpleFrameListener.h"

CSceneInBed :: CSceneInBed(COgreEngine &Creator, const String & Name, const int pos) : CSceneBase(Creator, Name, pos), m_pPluie(NULL), m_pPluieTop(NULL), m_ReflectCam(NULL), m_PlaneEnt(NULL)
{
}

CSceneInBed :: ~CSceneInBed(void)
{
}

void CSceneInBed :: Create(TCreatorEntities const &CreatorEntities, TCreatorNodes const &CreatorNodes, TCreatorLights const &CreatorLights, ENetConfig IsClient, Vector3 &CameraStartPos)
{	
	CSceneBase::Create(CreatorEntities, CreatorNodes, CreatorLights, IsClient, CameraStartPos);

    {
	    m_rttTex = m_OgreEngine.m_Root.getRenderSystem()->createRenderTexture( "InBedRttReflectTex", 1024, 1024, TEX_TYPE_2D, PF_R8G8B8 );
		m_ReflectCam = m_OgreEngine.m_pCurrentSceneManager->createCamera("InBedReflectCam");
        m_ReflectCam->setNearClipDistance(m_pCurrentCamera->getNearClipDistance());
        m_ReflectCam->setFarClipDistance(m_pCurrentCamera->getFarClipDistance());
        m_ReflectCam->setAspectRatio(m_pCurrentCamera->getAspectRatio());
		m_ReflectCam->setFOVy(m_resetParams.m_FOVy);

        Viewport *v = m_rttTex->addViewport( m_ReflectCam );
        v->setClearEveryFrame( true );
        v->setBackgroundColour( ColourValue::Black );

        MaterialPtr mat = MaterialManager::getSingleton().create("InBedRttReflectMat",
            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

		mat->setAmbient(0.5, 0.5, 0.5);
		mat->setDiffuse(0.5, 0.5, 0.5, 1);
		mat->setReceiveShadows(true);
        
        TextureUnitState *t = mat->getTechnique(0)->getPass(0)->createTextureUnitState("InBedRttReflectTex");
        // Blend with base texture
        t->setColourOperationEx(LBX_BLEND_MANUAL, LBS_TEXTURE, LBS_CURRENT, ColourValue::White, 
            ColourValue::White, 0.5);
		t->setTextureAddressingMode(TextureUnitState::TAM_BORDER);
		t->setProjectiveTexturing(true, m_ReflectCam);
        m_rttTex->addListener(this);

		MovablePlane * mPlane = new MovablePlane("InBedReflectPlane");
        mPlane->d = 0;
        mPlane->normal = Vector3::UNIT_Y;

		// set up linked reflection
        m_ReflectCam->enableReflection(mPlane);
        // Also clip
        m_ReflectCam->enableCustomNearClipPlane(mPlane);

	
        SceneNode *mPlaneNode = m_pSceneNode->createChildSceneNode();

        // Attach both the plane entity, and the plane definition
        //mPlaneNode->attachObject(m_PlaneEnt);
        //mPlaneNode->attachObject(mPlane);
        //mPlaneNode->translate(0, -10, 0);
        // Tilt it a little to make it interesting
        //mPlaneNode->roll(Degree(5));
	
		SceneNode *node = m_OgreEngine.m_pCurrentSceneManager->getSceneNode("inbed-sol-sol");
		node->attachObject(mPlane);

		// Give the plane a texture
		m_PlaneEnt = m_OgreEngine.m_pCurrentSceneManager->getEntity("inbed-sol-sol");
		m_PlaneEnt->setMaterialName("InBedRttReflectMat");
	}

	m_Compositors.push_back("Bloom");
	//m_Compositors.push_back("HDR");
}

void CSceneInBed :: Attach(void)
{
	CSceneBase::Attach();
	m_pCurrentCamera->setPosition(-177.330f, 40.945f, 1006.727f);
	//Quaternion Quat(Radian(Degree(0.0f)), Vector3(0, 1, 0));
	//m_pCurrentCamera->setOrientation(Quat);
	m_pCurrentCamera->setDirection(0, 0, -1);
	m_OgreEngine.m_pViewPort->setBackgroundColour(ColourValue(0.0f, 0.0f, 0.0f, 1.0f));
	m_rttTex->addListener(this);
}

void CSceneInBed :: Detach(void)
{
	CSceneBase::Detach();
	m_rttTex->removeListener(this);
}

bool CSceneInBed :: frameStarted(const FrameEvent& evt)
{
	/*
	{
		Entity *trucAnim = findEntity(String("truc_anim"));
		if (NULL != trucAnim && trucAnim->hasSkeleton())
		{
			Vector3 pos = trucAnim->getSkeleton()->getBone(0)->getPosition();
			Entity *truc = findEntity(String("inbed-sol-video"));
			if (NULL != truc && truc->hasSkeleton())
			{
				truc->getSkeleton()->getBone(0)->setPosition(pos);
			}
		}
	}
	*/

	CSceneBase::frameStarted(evt);

	m_ReflectCam->setPosition(m_pCurrentCamera->getPosition());
	m_ReflectCam->setOrientation(m_pCurrentCamera->getOrientation());

	MaterialPtr material = MaterialManager::getSingleton().getByName("inbed-wave/lambert1");
	if (NULL != material.getPointer())
	{
		GpuProgramParametersSharedPtr params = material->getTechnique(0)->getPass(0)->getVertexProgramParameters();
		if (NULL != params.getPointer())
		{
			GpuProgramParameters::RealConstantEntry * param = params->getRealConstantEntry(9);
			if (NULL != param)
			{
				Real final = 0.0f;
				Entity *entity = findEntity(String("inbed-clone-ana"));
				if (entity->hasSkeleton())
				{
					Radian angle;
					Vector3 axe(0,1,0);
					//entity->getSkeleton()->getBone("ATE_LeftShoulder")->getOrientation().ToAngleAxis(angle, axe);
					//param->val[0] = angle.valueRadians() / 3.14 * 0.005;
					Vector3 pos = entity->getSkeleton()->getBone("ATE_LeftForeArm")->getWorldPosition();
					final += pos.y / 100.0f * 0.001f;
				}
				entity = findEntity(String("inbed-clone-nco"));
				if (entity->hasSkeleton())
				{
					Radian angle;
					Vector3 axe(0,1,0);
					//entity->getSkeleton()->getBone("ATE_LeftShoulder")->getOrientation().ToAngleAxis(angle, axe);
					//param->val[0] = angle.valueRadians() / 3.14 * 0.005;
					Vector3 pos = entity->getSkeleton()->getBone("NCO_LeftForeArm")->getWorldPosition();
					final += pos.y / 100.0f * 0.001f;
				}

				param->val[0] = final;
			}
		}
	}

	if (m_pCameraFrameListener->mInputDevice->isKeyDown(KC_Z) && m_pCameraFrameListener->mTimeUntilNextToggle <= 0)
	{
		//m_OgreEngine.m_Root.setCurrentFrameNumber(0);
	}

	return (true);
}

// render target events
void CSceneInBed :: preRenderTargetUpdate(const RenderTargetEvent& evt)
{
	if (m_OgreEngine.m_pCurrentScene != this)
	{
		return;
	}
    // Hide plane 
    m_PlaneEnt->setVisible(false);

}
void CSceneInBed :: postRenderTargetUpdate(const RenderTargetEvent& evt)
{
	if (m_OgreEngine.m_pCurrentScene != this)
	{
		return;
	}
    // Show plane 
    m_PlaneEnt->setVisible(true);
}